﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.WebTesting;

namespace QA.TFS.Rules.Extraction
{
  public class EvaluateXPathQuery : ExtractionRule
  {

    public EvaluateXPathQuery() { }

    private string XPathQueryValue;
    public string XPathQuery
    {
      get { return XPathQueryValue; }
      set { XPathQueryValue = value; }
    }

    [DisplayName("Evaluate XPath Query")]
    [Description("Evaluates the given XPath Query")]
    public override void Extract(object sender, ExtractionEventArgs e)
    {

      XmlNamespaceManager nsManager = new XmlNamespaceManager(e.Response.XmlDocument.NameTable);
      nsManager.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");

      XPathNavigator navigator = e.Response.XmlDocument.CreateNavigator();
      XmlNode body = e.Response.XmlDocument.SelectSingleNode("//soap:Body", nsManager);

      // Very first child of soap response envelope's body tag is the response tag.
      string responseNameSpace = body.FirstChild.Attributes["xmlns"].Value;

      if (responseNameSpace != null && responseNameSpace.Length > 0)
      {

        nsManager.AddNamespace("response", responseNameSpace);

        // Now prefix temp namespace for every node in the query.
        int index = 0;

        while ((index = XPathQuery.IndexOf('/', index)) != -1)
        {

          if (XPathQuery[index + 1] == '/')
          {
            index++;
          }

          if (!XPathQuery.Substring(index + 1, 4).Equals("soap", StringComparison.InvariantCultureIgnoreCase))
          {
            XPathQuery = XPathQuery.Insert(index + 1, "response:");
          }

          ++index;
        }

      }

      XPathNodeIterator iterator = navigator.Evaluate(XPathQuery, nsManager) as XPathNodeIterator;
      if (iterator.Count > 0)
      {

        string val = string.Empty;
        while (iterator.MoveNext())
        {
          val += String.Format("{0}: {1}", iterator.Current.Name, iterator.Current.Value);
        }

        e.Success = true;
        e.WebTest.Context.Add(this.ContextParameterName, val);
      }
      else
      {
        e.Success = false;
        e.Message = String.Format(CultureInfo.CurrentCulture, "No result for query: {0}", XPathQuery);
      }
      return;

    }

  }

}
